home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1999 August / SGI Freeware 1999 August.iso / dist / fw_tkcvs.idb / usr / freeware / lib / tkcvs / bindings.tcl.z / bindings.tcl
Encoding:
Text File  |  1999-04-16  |  30.2 KB  |  1,199 lines

  1. # $Id: bindings.tcl,v 1.1 1995/01/14 11:27:00 del Exp $
  2. #
  3. # This code taken from tkMail by Paul Raines (raines@bohr.physics.upenn.edu)
  4. #
  5. # Gives more motif-like ands emacs-like bindings to Text and Entry Widgets
  6. #
  7. global bind_xnd btp
  8.  
  9. # USER SETTINGS
  10.  
  11. # maximum number of kills to save in ring
  12. set btp(maxkill) 10
  13. # maximum number of marks to save in ring
  14. set btp(maxmark) 10
  15. # syntax for letter not part of a "word"
  16. set btp(not-word) {[^a-zA-Z_0-9]}
  17. # procedure to use for errors
  18. set btp(error) error
  19. # procedure to use for beeping
  20. set btp(beep) ""
  21. # whether to bind Escape prefix commands also to the Meta modifier
  22. set btp(use-meta) 1
  23. # column at which to line wrap
  24. set btp(fillcol) 0
  25. # prefix for line wrapping (NOT REALLY WORKING YET)
  26. set btp(fillprefix) ""
  27.  
  28. # PRIVATE SETTINGS
  29.  
  30. set btp(lastkill) 0.0
  31. set btp(killring) ""
  32. set btp(killptr) 0
  33. set btp(killlen) 0
  34. set btp(arg) def
  35.  
  36. proc tk_entryForwspace w {
  37.      set x [expr [$w index insert] - 1]
  38.      catch {$w delete $x}
  39. }
  40.  
  41. # selection_if_any - return selection if it exists, else {}
  42. #   this is from kjx@comp.vuw.ac.nz (R. James Noble)
  43. proc selection_if_any {} {
  44.   if {[catch {selection get} s]} {return ""} {return $s}
  45. }
  46.  
  47. proc bind_cleanup { w } {
  48.     global btp
  49.     catch {unset btp($w,markring)}
  50. }
  51.  
  52. proc bt:current-line { w } {
  53.     return [lindex [split [$w index insert] .] 0]
  54. }
  55.  
  56. proc bt:current-col { w } {
  57.     return [lindex [split [$w index insert] .] 1]
  58. }
  59.  
  60. proc bt:move-line { w {num 1} } {
  61.     global btp
  62.     set btp(lastkill) 0.0
  63.     if {$btp(arg) != "def"} {
  64.     set num [expr $num*$btp(arg)]
  65.     set btp(arg) def
  66.     }
  67.     if {$btp(prevcmd) != "move-line"} {
  68.         set btp(goalcol) [lindex [split [$w index insert] .] 1]
  69.     }
  70.     if {$num > -1} {set num "+$num"}
  71.     $w tag remove sel 1.0 end
  72.     set ndx [$w index "insert $num line lineend"]
  73.     set goalndx [lindex [split $ndx .] 0].$btp(goalcol)
  74.     if {$btp(goalcol) < [lindex [split $ndx .] 1]} {
  75.         $w mark set insert $goalndx
  76.     } else {
  77.         $w mark set insert $ndx
  78.     }
  79.     $w yview -pickplace insert
  80.     set btp(prevcmd) move-line
  81. }
  82.  
  83. proc bt:move-char { w {num 1} } {
  84.     global btp
  85.     set btp(lastkill) 0.0
  86.     if {$btp(arg) != "def"} {
  87.     set num [expr $num*$btp(arg)]
  88.     set btp(arg) def
  89.     }
  90.     if {$num > -1} {set num "+$num"}
  91.     $w tag remove sel 1.0 end
  92.     $w mark set insert "insert $num char"
  93.     $w yview -pickplace insert
  94.     set btp(prevcmd) "move-char"
  95. }
  96.  
  97. proc bt:move-word {w {num 1}} {
  98.     global btp
  99.     set btp(lastkill) 0.0
  100.     $w tag remove sel 1.0 end
  101.     if {$btp(arg) != "def"} {
  102.     set num [expr $num*$btp(arg)]
  103.     set btp(arg) def
  104.     }
  105.     if {$num > 0} {
  106.         for {set i 0} {$i < $num } {incr i} {
  107.         while {[regexp $btp(not-word) [$w get insert]]} {
  108.             $w mark set insert insert+1c
  109.         } 
  110.         $w mark set insert {insert wordend}
  111.     }
  112.     } else {
  113.         for {set i 0} {$i > $num } {incr i -1} {
  114.         $w mark set insert insert-1c
  115.         while {[regexp $btp(not-word) [$w get insert]]} {
  116.             $w mark set insert insert-1c
  117.         } 
  118.         $w mark set insert {insert wordstart}
  119.     }
  120.     }
  121.     $w yview -pickplace insert
  122.     set btp(prevcmd) "move-word"
  123. }
  124.  
  125. proc bt:begin-line { w {num 0}} {
  126.     global btp
  127.     set btp(lastkill) 0.0
  128.     if {$btp(arg) != "def"} {
  129.     set num $btp(arg)
  130.     set btp(arg) def
  131.     }
  132.     if {$num != 0} {set num [expr $num-1]}
  133.     bt:move-line $w $num
  134.     $w mark set insert {insert linestart}
  135.     $w tag remove sel 1.0 end
  136.     $w yview -pickplace insert
  137.     set btp(prevcmd) "begin-line"
  138. }
  139.  
  140. proc bt:end-line { w {num 0}} {
  141.     global btp
  142.     set btp(lastkill) 0.0
  143.     if {$btp(arg) != "def"} {
  144.     set num $btp(arg)
  145.     set btp(arg) def
  146.     }
  147.     if {$num != 0} {set num [expr $num-1]}
  148.     bt:move-line $w $num
  149.     $w mark set insert {insert lineend}
  150.     $w tag remove sel 1.0 end
  151.     $w yview -pickplace insert
  152.     set btp(prevcmd) end-line
  153. }
  154.  
  155. proc bt:begin-buffer { w {num 0}} {
  156.     global btp
  157.     set btp(lastkill) 0.0
  158.     if {$btp(arg) != "def"} {
  159.     set num $btp(arg)
  160.     set btp(arg) def
  161.     }
  162.     bt:set-mark $w
  163.     set ndx [expr 1+[lindex [split [$w index end] .] 0]*$num/10]
  164.     $w mark set insert $ndx.0
  165.     $w tag remove sel 1.0 end
  166.     $w yview -pickplace insert
  167.     set btp(prevcmd) begin-buffer
  168. }
  169.  
  170. proc bt:end-buffer { w {num 0}} {
  171.     global btp
  172.     set btp(lastkill) 0.0
  173.     if {$btp(arg) != "def"} {
  174.     set num $btp(arg)
  175.     set btp(arg) def
  176.     }
  177.     bt:set-mark $w
  178.     set ndx [expr [lindex [split [$w index end] .] 0]*$num/10]
  179.     $w mark set insert "end - $ndx lines"
  180.     $w tag remove sel 1.0 end
  181.     $w yview -pickplace insert
  182.     set btp(prevcmd) end-buffer
  183. }
  184.  
  185. proc bt:scroll-next { w {num 1}} {
  186.     global  btp
  187.     set btp(lastkill) 0.0
  188.     if {$btp(arg) != "def"} {
  189.     set num $btp(arg)
  190.     set btp(arg) def
  191.     }
  192.     $w tag remove sel 1.0 end
  193.     set scr [lindex [lindex [$w configure -yscroll] 4] 0]
  194.     $w mark set insert [lindex [$scr get] 3].0
  195.     $w yview insert-1l
  196.     set btp(prevcmd) scroll-next
  197. }
  198.  
  199. proc bt:scroll-prior { w {num 1}} {
  200.     global btp
  201.     set btp(lastkill) 0.0
  202.     if {$btp(arg) != "def"} {
  203.     set num $btp(arg)
  204.     set btp(arg) def
  205.     }
  206.     $w tag remove sel 1.0 end
  207.     set scr [lindex [lindex [$w configure -yscroll] 4] 0]
  208.     set tndx [expr [lindex [$scr get] 2]-[lindex [$scr get] 1]+5].0
  209.     if {$tndx < 1.0} {set tndx 1.0}
  210.     $w mark set insert $tndx
  211.     $w yview insert-1l
  212.     set btp(prevcmd) scroll-prior
  213. }
  214.  
  215. proc bt:delete-word { w {num 1}} {
  216.     global btp
  217.     $w tag remove sel 1.0 end
  218.     if {[$w compare $btp(lastkill) == insert]} {
  219.     set lastcut [bt:pop-cut]
  220.     } else { set lastcut "" }
  221.     set beg [$w index insert]
  222.     if {$btp(arg) != "def"} {
  223.     set num $btp(arg)
  224.     set btp(arg) def
  225.     }
  226.     bt:move-word $w $num
  227.     puts "$num : $beg [$w index insert]"
  228.     if {$beg < [$w index insert]} {
  229.         bt:push-cut "$lastcut[$w get $beg insert]"
  230.         $w delete $beg insert
  231.     } else {
  232.         bt:push-cut "[$w get insert $beg]$lastcut"
  233.         $w delete insert $beg
  234.     }
  235.     set btp(lastkill) [$w index insert]
  236.     $w yview -pickplace insert
  237.     set btp(prevcmd) delete-word
  238. }
  239.  
  240. proc bt:delete-line { w {num 0}} {
  241.     global btp
  242.     $w tag remove sel 1.0 end
  243.     if {$btp(arg) != "def"} {
  244.     set num $btp(arg)
  245.     set btp(arg) def
  246.     }
  247.     if {[$w compare $btp(lastkill) == insert]} {
  248.     set lastcut [bt:pop-cut]
  249.     } else { set lastcut ""}
  250.     while {[$w get insert] == " "} {
  251.     $w mark set insert insert+1c
  252.     } 
  253.     if {[$w compare insert == "insert lineend"] && $num == 0} { set num 1 }
  254.     set beg [$w index insert]
  255.     if {$num != 0} {
  256.     bt:move-line $w $num
  257.     bt:begin-line $w
  258.     if {$beg < [$w index insert]} {
  259.         bt:push-cut "$lastcut[$w get $beg insert]"
  260.         $w delete $beg insert
  261.     } else {
  262.         bt:push-cut "[$w get insert $beg]$lastcut"
  263.         $w delete insert $beg
  264.     }
  265.     } else {
  266.       bt:push-cut "$lastcut[$w get insert {insert lineend}]"
  267.       $w delete insert {insert lineend};
  268.       $w yview -pickplace insert
  269.     }
  270.     $w yview -pickplace insert
  271.     set btp(lastkill) [$w index insert]
  272.     set btp(prevcmd) delete-line
  273. }
  274.  
  275. proc bt:delete-back-char-or-sel { w {num 1} } {
  276.     global btp
  277.     if {$btp(arg) != "def"} {
  278.         set num $btp(arg)
  279.     } else {set btp(lastkill) 0.0}
  280.     set num [expr -1*$num]
  281.     if {$num > -1} {set num "+$num"}
  282.     if {[$w compare $btp(lastkill) == insert]} {
  283.     set lastcut [bt:pop-cut]
  284.     } else { set lastcut ""}
  285.     if [catch {set tmp [$w get sel.first sel.last]}] {
  286.         if {$btp(arg) != "def"} {
  287.         if {$num < 0} {
  288.         bt:push-cut "[$w get "insert $num char" insert]$lastcut"
  289.             $w delete "insert $num char" insert
  290.         } else {
  291.         bt:push-cut "$lastcut[$w get insert "insert $num char"]"
  292.             $w delete insert "insert $num char"
  293.         }
  294.         set btp(lastkill) [$w index insert]
  295.         } else {
  296.         if {$num < 0} {
  297.             $w delete "insert $num char" insert
  298.         } else {
  299.             $w delete insert "insert $num char"
  300.         }
  301.         set btp(lastkill) 0.0
  302.         }
  303.     } else {
  304.     $w delete sel.first sel.last
  305.     bt:push-cut $tmp
  306.         set btp(lastkill) 0.0
  307.     }
  308.     set btp(arg) def
  309.     $w yview -pickplace insert
  310.     set btp(prevcmd) delete-back-char-or-sel
  311. }
  312.  
  313. proc bt:delete-region-or-sel { w } {
  314.     global btp
  315.  
  316.     if {[catch {set tmp [$w get sel.first sel.last]}]} {
  317.     if {[catch "$w index emacs"]} {
  318.         $btp(error) "No emacs mark has been set yet!"
  319.     }
  320.         if {[$w compare $btp(lastkill) == insert]} {
  321.         set lastcut [bt:pop-cut]
  322.         } else { set lastcut ""}
  323.     if {[$w compare emacs < insert]} {
  324.         bt:push-cut "$lastcut[$w get emacs insert]"
  325.         $w delete emacs insert
  326.     } else {
  327.         bt:push-cut "[$w get insert emacs]$lastcut"
  328.         $w delete insert emacs
  329.     }
  330.         set btp(lastkill) [$w index insert]
  331.     } else {
  332.     $w delete sel.first sel.last
  333.     bt:push-cut $tmp
  334.         set btp(lastkill) 0.0
  335.     }
  336.     set btp(arg) def
  337.     set btp(prevcmd) delete-region-or-sel
  338. }
  339.  
  340. proc bt:copy-region-or-sel { w } {
  341.     global btp
  342.  
  343.     if {[catch {set tmp [$w get sel.first sel.last]}]} {
  344.     if {[catch "$w index emacs"]} {
  345.         $btp(error) "No emacs mark has been set yet!"
  346.     }
  347.         if {[$w compare $btp(lastkill) == insert]} {
  348.         set lastcut [bt:pop-cut]
  349.         } else { set lastcut ""}
  350.     if {[$w compare emacs < insert]} {
  351.         bt:push-cut "$lastcut[$w get emacs insert]"
  352.     } else {
  353.         bt:push-cut "[$w get insert emacs]$lastcut"
  354.     }
  355.     bt:exchange-point-and-mark $w
  356.     after 200 bt:exchange-point-and-mark $w
  357.     } else {
  358.     bt:push-cut $tmp
  359.     }
  360.     set btp(arg) def
  361.     set btp(lastkill) 0.0
  362.     set btp(prevcmd) copy-region-or-sel
  363. }
  364.  
  365. proc bt:append-next-kill { w } {
  366.     global btp
  367.     set btp(lastkill) [$w index insert]
  368. }
  369.  
  370. proc bt:push-cut { txt } {
  371.     global btp
  372.  
  373.     set btp(killlen) [llength [lappend btp(killring) $txt]]
  374.     if { $btp(killlen) > $btp(maxkill)} {
  375.     set btp(killring) [lreplace $btp(killring) 0 0]
  376.     incr btp(killlen) -1
  377.     }
  378.     set btp(killptr) 0
  379. }
  380.  
  381. proc bt:pop-cut { } {
  382.     global btp
  383.  
  384.     if {$btp(killlen) == 0} {return ""}
  385.     set txt [bt:get-cut 1]
  386.     set ndx [expr $btp(killlen)-1]
  387.     set btp(killring) [lreplace $btp(killring) $ndx $ndx ]
  388.     incr btp(killlen) -1
  389.     set btp(killptr) 0
  390.     return $txt
  391. }
  392.  
  393. proc bt:get-cut { {ndx 1} } {
  394.     global btp
  395.  
  396.     set ndx [expr $ndx+$btp(killptr)]
  397.     set btp(killptr) [expr $ndx-1]
  398.     set ndx [expr $ndx%$btp(killlen)]
  399.     if {$ndx == 0} {set ndx $btp(killlen)}
  400.     return [lindex $btp(killring) [expr $btp(killlen)-$ndx]]
  401.  
  402. }
  403.  
  404. proc bt:yank { w {num 1}} {
  405.     global btp
  406.     $w tag remove sel 1.0 end
  407.     if {$btp(arg) != "def"} {
  408.     set num $btp(arg)
  409.     set btp(arg) def
  410.     }
  411.     set btp(lastkill) 0.0
  412.     set tmp [$w index insert]
  413.     $w insert insert [bt:get-cut $num]
  414.     $w mark set emacs $tmp
  415.     $w yview -pickplace insert
  416.     set btp(prevcmd) yank
  417. }
  418.  
  419. proc bt:yank-pop { w {num 1}} {
  420.     global btp
  421.     if {$btp(arg) != "def"} {
  422.     set num $btp(arg)
  423.     set btp(arg) def
  424.     }
  425.     if {$btp(prevcmd) != "yank"} return
  426.     $w tag remove sel 1.0 end
  427.     $w delete emacs insert
  428.     set tmp [$w index insert]
  429.     $w insert insert [bt:get-cut [expr $num+1]]
  430.     $w mark set emacs $tmp
  431.     $w yview -pickplace insert
  432. }
  433.  
  434. proc bt:pop-mark { w } {
  435.     global btp
  436.     set ndx [expr [llength $btp($w,markring)]-1]
  437.     set oldmark [lindex $btp($w,markring) $ndx]
  438.     $w mark set emacs $oldmark
  439.     set btp($w,markring) [concat $oldmark [lreplace $btp($w,markring) $ndx $ndx]]
  440. }
  441.  
  442. proc bt:push-mark { w ndx } {
  443.     global btp
  444.     lappend btp($w,markring) $ndx
  445. }
  446.  
  447. proc bt:set-mark { w {num def}} {
  448.     global btp
  449.     $w tag remove sel 1.0 end
  450.     if {$btp(arg) != "def"} {
  451.     set num $btp(arg)
  452.     set btp(arg) def
  453.     }
  454.     if {$num != "def"} {
  455.     if {[catch "$w index emacs"]} {
  456.         $btp(error) "No emacs mark has been set yet!"
  457.     }
  458.         $w yview -pickplace insert
  459.         bt:pop-mark $w
  460.         $w mark set insert emacs
  461.     } else {
  462.     bt:push-mark $w [$w index insert]
  463.         $w mark set emacs insert
  464.     }
  465.     set btp(lastkill) 0.0
  466.     set btp(prevcmd) set-mark
  467. }
  468.  
  469. proc bt:exchange-point-and-mark { w } {
  470.     global btp
  471.     if {[catch "$w index emacs"]} {
  472.     $btp(error) "No emacs mark has been set yet!"
  473.     }
  474.     set tmp [$w index insert]
  475.     $w mark set insert emacs
  476.     $w mark set emacs $tmp
  477.     set btp(lastkill) 0.0
  478.     set btp(prevcmd) set-mark
  479. }
  480.  
  481. proc bt:open-line {w {num 1}} {
  482.     global btp
  483.     if {$btp(arg) != "def"} {
  484.     set num $btp(arg)
  485.     set btp(arg) def
  486.     }
  487.     catch {$w delete sel.first sel.last}
  488.     for {set i 0} {$i < $num } {incr i} {
  489.         $w insert insert \n
  490.     }
  491.     $w mark set insert insert-1c
  492.     $w yview -pickplace insert
  493.     set btp(prevcmd) open-line
  494. }
  495.  
  496. proc bt:argkey { w a } {
  497.     global btp
  498.     set btp(arg) $a
  499.  
  500. proc bt:numkey { w a } {
  501.     global btp
  502.     if {$btp(arg) == "def"} {
  503.     catch {%W delete sel.first sel.last}
  504.     $w insert insert $a
  505.     if {$btp(fillcol) && [bt:current-col $w] >= $btp(fillcol)} {
  506.         bt:wrap-word $w
  507.     }
  508.     $w yview -pickplace insert
  509.     set btp(lastkill) 0.0
  510.     set btp(prevcmd) self-insert
  511.     } else {
  512.     if {$a == "-"} {
  513.         if {$btp(arg) == "-"} { 
  514.         set btp(arg) "0" 
  515.         } elseif {$btp(arg) == "0"} {
  516.         set btp(arg) "-"
  517.         } else {
  518.         set btp(arg) [expr -1*$btp(arg)]
  519.         }
  520.     } else {
  521.         append btp(arg) $a
  522.     }
  523.     }
  524.  
  525. proc bt:univ-arg { w } {
  526.     global btp
  527.     if {$btp(arg) == "def"} {
  528.     set btp(arg) 4
  529.     } else {
  530.     if {$btp(arg) == "-"} { 
  531.         set btp(arg) "-4" 
  532.     } else {
  533.         set btp(arg) [expr 4*$btp(arg)]
  534.     }
  535.     }
  536. }
  537.  
  538. proc bt:wrap-word { w } {
  539.     global btp
  540.  
  541.     bt:move-word $w -1
  542.     $w insert insert \n
  543.     bt:end-line $w
  544. }
  545.  
  546. proc bt:set-fill-col { w {num 0}} {
  547.     global btp
  548.     if {$btp(arg) == "def"} {
  549.     if {$num < 1} {
  550.         set btp(fillcol) [bt:current-col $w]
  551.     } else {
  552.         set btp(fillcol) $num
  553.     }
  554.     } else {
  555.     if {$btp(arg) < 1} {
  556.         set btp(fillcol) [bt:current-col $w]
  557.     } else {
  558.         set btp(fillcol) $btp(arg)
  559.     }
  560.     }
  561.     set btp(arg) def
  562.     set btp(lastkill) 0.0
  563.     set btp(prevcmd) set-fill-col
  564. }
  565.  
  566. proc bind_motiftext { tw } {
  567.     global bind_xnd
  568.  
  569.     bind $tw <Control-KeyPress> {
  570.         global btp
  571.     if {"%A" != ""} {eval $btp(beep) }
  572.     }
  573.  
  574.     # Some better bindings for text and entry
  575.     bind $tw <Up> {bt:move-line %W -1}
  576.     bind $tw <Down> {bt:move-line %W 1}
  577.     bind $tw <Left> {bt:move-char %W -1}
  578.     bind $tw <Right> {bt:move-char %W 1}
  579.     bind $tw <Home> {bt:begin-line %W}
  580.     bind $tw <End> {bt:end-line %W}
  581.     bind $tw <Control-Home> {bt:begin-buffer %W}
  582.     bind $tw <Control-End> {bt:end-buffer %W}
  583.     bind $tw <Control-Left> {bt:move-word %W -1}
  584.     bind $tw <Control-Right> {bt:move-word %W 1}
  585.     bind $tw <Next> {bt:scroll-next %W}
  586.     bind $tw <Prior> {bt:scroll-prior %W}
  587.  
  588.     bind $tw <Any-KeyPress> {
  589.     global btp
  590.     set num 1
  591.     if {"%A" != ""} {
  592.         if {$btp(arg) != "def"} {
  593.         set num $btp(arg)
  594.         set btp(arg) def
  595.         }
  596.         catch {%W delete sel.first sel.last}
  597.         for {set i 0} { $i < $num} {incr i} {%W insert insert %A}
  598.         if {$btp(fillcol) && [bt:current-col %W] >= $btp(fillcol)} {
  599.         if {"%A" == " "} {
  600.             %W insert insert \n
  601.         } elseif {"%A" == "\t"} {
  602.             %W insert insert \n\t
  603.         } else {
  604.             bt:wrap-word %W
  605.         }
  606.         }
  607.         %W yview -pickplace insert
  608.         set btp(lastkill) 0.0
  609.         set btp(prevcmd) self-insert
  610.     }
  611.     }
  612.  
  613.     bind $tw <KeyPress-Return> {
  614.     global btp
  615.         catch {%W delete sel.first sel.last}
  616.     set num 1
  617.     if {$btp(arg) != "def"} {
  618.         set num $btp(arg)
  619.         set btp(arg) def
  620.     }
  621.         for {set i 0} { $i < $num} {incr i} {%W insert insert "\n"}
  622.         %W yview -pickplace insert
  623.     set btp(lastkill) 0.0
  624.     set btp(prevcmd) newline
  625.     }
  626.  
  627.     bind $tw <KeyPress-Delete> {bt:delete-back-char-or-sel %W -1}
  628.     bind $tw <KeyPress-BackSpace> {bt:delete-back-char-or-sel %W 1}
  629.  
  630.     bind $tw <1> "[bind Text <1>]; \
  631.                   global btp; set btp(lastkill) 0.0; \
  632.           set btp(prevcmd) mouse-set"
  633.     bind $tw <3> {%W tag remove sel 1.0 end}
  634.     bind $tw <B1-Motion> {bind_textB1motion %W @%x,%y}
  635.  
  636.     set bind_xnd(b2-time) 0
  637.     set bind_xnd(b2-y) 0
  638.     bind $tw <2> {
  639.         global bind_xnd
  640.         %W scan mark %y
  641.         set bind_xnd(b2-time) %t
  642.         set bind_xnd(b2-y) %y
  643.     }
  644.     bind $tw <ButtonRelease-2> {
  645.         global bind_xnd
  646.     if {[expr %t-$bind_xnd(b2-time)]<1000} {
  647.         %W insert insert [selection_if_any]
  648.          global btp
  649.         set btp(lastkill) 0.0
  650.         set btp(prevcmd) mouse-insert
  651.         }
  652.     }
  653.  
  654.     # only one mouse, so no need have separate vars for each widget
  655.     set bind_xnd(txnd) 0
  656.     set bind_xnd(xdelay) 100
  657.     proc bind_textB1motion  { w loc } {
  658.     global bind_xnd
  659.  
  660.     set ypos [lindex [split $loc ","] 1]
  661.     if {$ypos > [winfo height $w]} {
  662.         if {!$bind_xnd(txnd)} {after $bind_xnd(xdelay) bind_textExtend $w}
  663.         set bind_xnd(txnd) 1
  664.         set bind_xnd(direction) down
  665.     } elseif {$ypos < 0} {
  666.         if {!$bind_xnd(txnd)} {after $bind_xnd(xdelay) bind_textExtend $w}
  667.         set bind_xnd(txnd) 1
  668.         set bind_xnd(direction) up
  669.     } else {
  670.         set bind_xnd(txnd) 0
  671.         set bind_xnd(direction) 0
  672.     }
  673.  
  674.     if {!$bind_xnd(txnd)} {
  675.         tk_textSelectTo $w $loc
  676.     }
  677.  
  678.     }
  679.  
  680.     bind $tw <ButtonRelease-1> { 
  681.         global bind_xnd btp
  682.         set bind_xnd(txnd) 0
  683.     set btp(lastkill) 0.0
  684.     set btp(prevcmd) mouse-select
  685.     }
  686.  
  687.     proc bind_textExtend { w } {
  688.      global bind_xnd
  689.  
  690.      if {$bind_xnd(txnd)} {
  691.          if {$bind_xnd(direction) == "down"} {
  692.          tk_textSelectTo $w sel.last+1l
  693.          $w yview -pickplace sel.last+1l
  694.          } elseif {$bind_xnd(direction) == "up"} {
  695.          tk_textSelectTo $w sel.first-1l
  696.          $w yview -pickplace sel.first-1l
  697.          } else { return }
  698.          after $bind_xnd(xdelay) bind_textExtend $w
  699.      }
  700.     }
  701.  
  702. }
  703.  
  704. proc bind_emacstext { tw } {
  705.     global btp
  706.  
  707.     # make Escape key simulate a state Alt key
  708.     bind $tw <Escape> { }
  709.     bind $tw <Escape><Any-KeyPress> {
  710.         global btp
  711.     if {"%A" != ""} {eval $btp(beep) }
  712.     }
  713.  
  714.     bind $tw <Control-a> {bt:begin-line %W}
  715.     bind $tw <Control-e> {bt:end-line %W}
  716.     bind $tw <Control-f> {bt:move-char %W 1}
  717.     bind $tw <Control-b> {bt:move-char %W -1}
  718.     bind $tw <Escape><f> {bt:move-word %W 1}
  719.     bind $tw <Escape><b> {bt:move-word %W -1}
  720.  
  721.     bind $tw <Control-n> {bt:move-line %W 1}
  722.     bind $tw <Control-p> {bt:move-line %W -1}
  723.     bind $tw <Control-l> {
  724.     %W yview -pickplace insert
  725.     }
  726.     bind $tw <Control-o> {bt:open-line %W 1}
  727.     bind $tw <Control-d> {bt:delete-back-char-or-sel %W -1}
  728.     bind $tw <Escape><d> {bt:delete-word %W 1}
  729.  
  730.     bind $tw <Control-h> {bt:delete-back-char-or-sel %W -1}
  731.  
  732.     bind $tw <Control-k> {bt:delete-line %W 0}
  733.     bind $tw <Control-w> {bt:delete-region-or-sel %W}
  734.     bind $tw <Escape><w> {bt:copy-region-or-sel %W}
  735.     bind $tw <Control-y> {bt:yank %W}
  736.     bind $tw <Escape><y> {bt:yank-pop %W}
  737.     bind $tw <Control-space> {bt:set-mark %W}
  738.  
  739.     bind $tw <Control-u> {bt:univ-arg %W}
  740.     bind $tw <KeyPress-0> {bt:numkey %W %A}
  741.     bind $tw <KeyPress-1> {bt:numkey %W %A}
  742.     bind $tw <KeyPress-2> {bt:numkey %W %A}
  743.     bind $tw <KeyPress-3> {bt:numkey %W %A}
  744.     bind $tw <KeyPress-4> {bt:numkey %W %A}
  745.     bind $tw <KeyPress-5> {bt:numkey %W %A}
  746.     bind $tw <KeyPress-6> {bt:numkey %W %A}
  747.     bind $tw <KeyPress-7> {bt:numkey %W %A}
  748.     bind $tw <KeyPress-8> {bt:numkey %W %A}
  749.     bind $tw <KeyPress-9> {bt:numkey %W %A}
  750.  
  751.     bind $tw <Escape><KeyPress-0> {bt:argkey %W %A}
  752.     bind $tw <Escape><KeyPress-1> {bt:argkey %W %A}
  753.     bind $tw <Escape><KeyPress-2> {bt:argkey %W %A}
  754.     bind $tw <Escape><KeyPress-3> {bt:argkey %W %A}
  755.     bind $tw <Escape><KeyPress-4> {bt:argkey %W %A}
  756.     bind $tw <Escape><KeyPress-5> {bt:argkey %W %A}
  757.     bind $tw <Escape><KeyPress-6> {bt:argkey %W %A}
  758.     bind $tw <Escape><KeyPress-7> {bt:argkey %W %A}
  759.     bind $tw <Escape><KeyPress-8> {bt:argkey %W %A}
  760.     bind $tw <Escape><KeyPress-9> {bt:argkey %W %A}
  761.     bind $tw <Escape><KeyPress-minus> {bt:argkey %W %A}
  762.  
  763.     # make C-x key a state
  764.     bind $tw <Control-x> { }
  765.     bind $tw <Control-x><Any-KeyPress> {
  766.         global btp
  767.     if {"%A" != ""} {eval $btp(beep) }
  768.     }
  769.     bind $tw <Control-x><Control-x> {bt:exchange-point-and-mark %W}
  770.     bind $tw <Control-x><KeyPress-f> {bt:set-fill-col %W}
  771.  
  772.     # Make Meta key like and Escape prefix
  773.     if {$btp(use-meta)} {
  774.     bind $tw <Meta-KeyPress> {
  775.         global btp
  776.         if {"%A" != ""} {eval $btp(beep) }
  777.     }
  778.     bind $tw <Control-Meta-KeyPress> {
  779.         global btp
  780.         if {"%A" != ""} {eval $btp(beep) }
  781.     }
  782.  
  783.     bind $tw <Meta-f> {bt:move-word %W 1}
  784.     bind $tw <Meta-b> {bt:move-word %W -1}
  785.     bind $tw <Meta-d> {bt:delete-word %W 1}
  786.     bind $tw <Meta-w> {bt:copy-region-or-sel %W}
  787.     bind $tw <Meta-y> {bt:yank-pop %W}
  788.  
  789.     bind $tw <Meta-0> {bt:argkey %W %A}
  790.     bind $tw <Meta-1> {bt:argkey %W %A}
  791.     bind $tw <Meta-2> {bt:argkey %W %A}
  792.     bind $tw <Meta-3> {bt:argkey %W %A}
  793.     bind $tw <Meta-4> {bt:argkey %W %A}
  794.     bind $tw <Meta-5> {bt:argkey %W %A}
  795.     bind $tw <Meta-6> {bt:argkey %W %A}
  796.     bind $tw <Meta-7> {bt:argkey %W %A}
  797.     bind $tw <Meta-8> {bt:argkey %W %A}
  798.     bind $tw <Meta-9> {bt:argkey %W %A}
  799.     bind $tw <Meta-minus> {bt:argkey %W %A}
  800.     }
  801. }
  802.  
  803. ##############
  804. # ENTRY WIDGET
  805. ##############
  806.  
  807. proc be:move-char {w {num 1} } {
  808.     global btp
  809.     set btp(lastkill-entry) -1
  810.     if {$btp(arg) != "def"} {
  811.     set num [expr $num*$btp(arg)]
  812.     set btp(arg) def
  813.     }
  814.     $w select clear
  815.     $w icursor [expr {[$w index insert] + $num}]
  816.     tk_entrySeeCaret $w
  817.     set btp(prevcmd) move-char
  818. }
  819.  
  820. proc be:move-word {w {num 1}} {
  821.     global btp
  822.     set btp(lastkill-entry) -1
  823.     $w select clear
  824.     if {$btp(arg) != "def"} {
  825.     set num [expr $num*$btp(arg)]
  826.     set btp(arg) def
  827.     }
  828.     if {$num > 0} {
  829.         for {set i 0} {$i < $num } {incr i} {
  830.         set endx [expr [$w index insert]+1]
  831.         set estr [$w get]
  832.         while {$endx < [string length $estr] &&
  833.           [regexp $btp(not-word) [string index $estr $endx]]} {
  834.             incr endx
  835.         }
  836.         while {$endx < [string length $estr] &&
  837.           ![regexp $btp(not-word) [string index $estr $endx]]} {
  838.             incr endx
  839.         } 
  840.         $w icursor $endx
  841.     }
  842.     } else {
  843.         for {set i 0} {$i > $num } {incr i -1} {
  844.         set endx [expr [$w index insert]-2]
  845.         set estr [$w get]
  846.         while {$endx > 0 &&
  847.            [regexp $btp(not-word) [string index $estr $endx]]} {
  848.             incr endx -1
  849.         }
  850.         while {$endx > 0 &&
  851.            ![regexp $btp(not-word) [string index $estr $endx]]} {
  852.             incr endx -1
  853.         }
  854.         if {$endx > 1} {incr endx}
  855.         $w icursor $endx
  856.     }
  857.     }
  858.     tk_entrySeeCaret $w
  859.     set btp(prevcmd) "move-word"
  860. }
  861.  
  862. proc be:begin-line { w } {
  863.     global btp
  864.     set btp(lastkill-entry) -1
  865.     $w select clear
  866.     $w icursor 0
  867.     tk_entrySeeCaret $w
  868.     set btp(arg) def
  869.     set btp(prevcmd) begin-line
  870. }
  871.  
  872. proc be:end-line { w } {
  873.     global btp
  874.     set btp(lastkill-entry) -1
  875.     $w select clear
  876.     $w icursor end
  877.     tk_entrySeeCaret $w
  878.     set btp(arg) def
  879.     set btp(prevcmd) end-line
  880. }
  881.  
  882. proc be:delete-back-char-or-sel { w {num 1} } {
  883.     global btp
  884.     set btp(lastkill-entry) -1
  885.     if {$btp(arg) != "def"} {
  886.     set num [expr $num*$btp(arg)]
  887.     set btp(arg) def
  888.     }
  889.     if {[catch {$w delete sel.first sel.last}] != 0} {
  890.         set x [expr [$w index insert] - $num]
  891.         catch {$w delete $x}
  892.     tk_entrySeeCaret $w
  893.     }
  894.     set btp(prevcmd) delete-back-char-or-sel
  895. }
  896.  
  897. proc be:delete-word { w {num 1}} {
  898.     global btp
  899.     $w select clear
  900.     if {$btp(lastkill-entry) == [$w index insert]} {
  901.     set lastcut [bt:pop-cut]
  902.     } else { set lastcut "" }
  903.     set beg [$w index insert]
  904.     if {$btp(arg) != "def"} {
  905.     set num $btp(arg)
  906.     set btp(arg) def
  907.     }
  908.     be:move-word $w $num
  909.     set endx [$w index insert]
  910.     if {$beg < $endx} {
  911.     incr endx -1
  912.     bt:push-cut "$lastcut[string range [$w get] $beg $endx]"
  913.     $w delete $beg $endx
  914.     } else {
  915.     incr beg -1
  916.     bt:push-cut "[string range [$w get] $endx $beg]$lastcut"
  917.     $w delete $endx $beg
  918.     }
  919.     set btp(lastkill-entry) [$w index insert]
  920.     tk_entrySeeCaret $w
  921.     set btp(prevcmd) delete-word
  922. }
  923.  
  924. proc be:delete-line { w } {
  925.     global btp
  926.     if {$btp(lastkill-entry) == [$w index insert]} {
  927.     set lastcut [bt:pop-cut]
  928.     } else { set lastcut "" }
  929.     $w select clear
  930.     bt:push-cut "$lastcut[string range [$w get] [$w index insert] end]"
  931.     $w delete [$w index insert] end
  932.     set btp(lastkill-entry) [$w index insert]
  933.     tk_entrySeeCaret $w
  934.     set btp(arg) def
  935.     set btp(prevcmd) delete-line
  936. }
  937.  
  938. proc be:delete-region-or-sel { w } {
  939.     global btp
  940.     if {[catch "$w index sel.first"]} {
  941.     $btp(error) "Sorry! No emacs mark for entries yet!"
  942.     } else {
  943.     bt:push-cut [selection_if_any]
  944.     $w delete sel.first sel.last
  945.     }
  946.     tk_entrySeeCaret $w
  947.     set btp(lastkill-entry) -1
  948.     set btp(arg) def
  949.     set btp(prevcmd) delete-region-or-sel
  950. }
  951.  
  952. proc be:copy-region-or-sel { w } {
  953.     global btp
  954.     if {[catch "$w index sel.first"]} {
  955.     $btp(error) "Sorry! No emacs mark for entries yet!"
  956.     } else {
  957.     bt:push-cut [selection_if_any]
  958.     $w select clear
  959.     }
  960.     tk_entrySeeCaret $w
  961.     set btp(lastkill-entry) -1
  962.     set btp(arg) def
  963.     set btp(prevcmd) copy-region-or-sel
  964. }
  965.  
  966. proc be:append-next-kill { w } {
  967.     global btp
  968.     set btp(lastkill-entry) [$w index insert]
  969. }
  970.  
  971. proc be:yank { w {num 1}} {
  972.     global btp
  973.     $w select clear
  974.     if {$btp(arg) != "def"} {
  975.     set num $btp(arg)
  976.     set btp(arg) def
  977.     }
  978.     set btp(lastkill-entry) -1
  979.     set btp(entry-yank-mark) [$w index insert]
  980.     $w insert insert [bt:get-cut $num]
  981.     tk_entrySeeCaret $w
  982.     set btp(prevcmd) yank
  983. }
  984.  
  985. proc be:yank-pop { w {num 1}} {
  986.     global btp
  987.     if {$btp(arg) != "def"} {
  988.     set num $btp(arg)
  989.     set btp(arg) def
  990.     }
  991.     if {$btp(prevcmd) != "yank"} return
  992.     $w select clear
  993.     $w delete $btp(entry-yank-mark) [expr [$w index insert]-1]
  994.     $w insert insert [bt:get-cut [expr $num+1]]
  995.     tk_entrySeeCaret $w
  996. }
  997.  
  998. proc be:set-mark { w } {
  999.     global btp
  1000.     $btp(error) "Sorry! No emacs mark for entries yet!"
  1001. }
  1002.  
  1003.  
  1004. proc be:exchange-point-and-mark { w } {
  1005.     global btp
  1006.     $btp(error) "Sorry! No emacs mark for entries yet!"
  1007. }
  1008.  
  1009. proc be:argkey { w a } {
  1010.     global btp
  1011.     set btp(arg) $a
  1012.  
  1013. proc be:numkey { w a } {
  1014.     global btp
  1015.     if {$btp(arg) == "def"} {
  1016.     catch {%W delete sel.first sel.last}
  1017.     $w insert insert $a
  1018.     tk_entrySeeCaret $w
  1019.     set btp(lastkill-entry) -1
  1020.     set btp(prevcmd) self-insert
  1021.     } else {
  1022.     if {$a == "-"} {
  1023.         if {$btp(arg) == "-"} { 
  1024.         set btp(arg) "0" 
  1025.         } elseif {$btp(arg) == "0"} {
  1026.         set btp(arg) "-"
  1027.         } else {
  1028.         set btp(arg) [expr -1*$btp(arg)]
  1029.         }
  1030.     } else {
  1031.         append btp(arg) $a
  1032.     }
  1033.     }
  1034.  
  1035. proc be:univ-arg { w } {
  1036.     global btp
  1037.     if {$btp(arg) == "def"} {
  1038.     set btp(arg) 4
  1039.     } else {
  1040.     if {$btp(arg) == "-"} { 
  1041.         set btp(arg) "-4" 
  1042.     } else {
  1043.         set btp(arg) [expr 4*$btp(arg)]
  1044.     }
  1045.     }
  1046. }
  1047.  
  1048. proc bind_motifentry { ew } {
  1049.     global bind_xnd
  1050.  
  1051.     bind $ew <Control-KeyPress> {
  1052.         global btp
  1053.     if {"%A" != ""} {eval $btp(beep) }
  1054.     }
  1055.  
  1056.     bind $ew <Delete> {be:delete-back-char-or-sel %W -1}
  1057.     bind $ew <BackSpace> {be:delete-back-char-or-sel %W 1}
  1058.     bind $ew <Left> {be:move-char %W -1}
  1059.     bind $ew <Right> {be:move-char %W 1}
  1060.     bind $ew <Control-Left> {be:move-word %W -1}
  1061.     bind $ew <Control-Right> {be:move-word %W 1}
  1062.     bind $ew <Home> {be:begin-line %W}
  1063.     bind $ew <End> {be:end-line %W}
  1064.  
  1065.     bind $ew <Any-KeyPress> {
  1066.         global btp
  1067.     if {"%A" != ""} {
  1068.         catch {%W delete sel.first sel.last}
  1069.         %W insert insert %A
  1070.         tk_entrySeeCaret %W
  1071.         set btp(lastkill-entry) -1
  1072.         set btp(prevcmd) self-insert
  1073.     }
  1074.     }
  1075.  
  1076.     bind $ew <1> "[bind Entry <1>]; \
  1077.                   global btp; set btp(lastkill-entry) -1; \
  1078.           set btp(prevcmd) mouse-set"
  1079.     bind $ew <Double-Button-1> {%W select from 0; %W select to end}
  1080.     bind $ew <3> {%W select clear}
  1081.     bind $ew <Shift-2> {%W scan mark %x}
  1082.     bind $ew <Shift-B2-Motion> {%W scan dragto %x}
  1083.  
  1084.     set bind_xnd(b2-time) 0
  1085.     bind $ew <2> {
  1086.         global bind_xnd
  1087.         %W scan mark %x
  1088.         set bind_xnd(b2-time) %t
  1089.     }
  1090.     bind $ew <ButtonRelease-2> {
  1091.         global bind_xnd btp
  1092.     if {[expr %t-$bind_xnd(b2-time)]<1000} {
  1093.         set btp(lastkill-entry) -1
  1094.         %W insert insert [selection_if_any]
  1095.          set btp(prevcmd) mouse-insert
  1096.         }
  1097.     }
  1098.  
  1099. }
  1100.  
  1101. proc bind_emacsentry { ew } {
  1102.     global btp
  1103.  
  1104.     # make Escape key simulate Alt key
  1105.     bind $ew <Escape> { }
  1106.     bind $ew <Escape><Any-KeyPress> {
  1107.         global btp
  1108.     if {"%A" != ""} {eval $btp(beep) }
  1109.     }
  1110.  
  1111.     bind $ew <KeyPress-0> {be:numkey %W %A}
  1112.     bind $ew <KeyPress-1> {be:numkey %W %A}
  1113.     bind $ew <KeyPress-2> {be:numkey %W %A}
  1114.     bind $ew <KeyPress-3> {be:numkey %W %A}
  1115.     bind $ew <KeyPress-4> {be:numkey %W %A}
  1116.     bind $ew <KeyPress-5> {be:numkey %W %A}
  1117.     bind $ew <KeyPress-6> {be:numkey %W %A}
  1118.     bind $ew <KeyPress-7> {be:numkey %W %A}
  1119.     bind $ew <KeyPress-8> {be:numkey %W %A}
  1120.     bind $ew <KeyPress-9> {be:numkey %W %A}
  1121.  
  1122.     bind $ew <Control-u> {be:univ-arg %W}
  1123.     bind $ew <Escape><KeyPress-0> {be:argkey %W %A}
  1124.     bind $ew <Escape><KeyPress-1> {be:argkey %W %A}
  1125.     bind $ew <Escape><KeyPress-2> {be:argkey %W %A}
  1126.     bind $ew <Escape><KeyPress-3> {be:argkey %W %A}
  1127.     bind $ew <Escape><KeyPress-4> {be:argkey %W %A}
  1128.     bind $ew <Escape><KeyPress-5> {be:argkey %W %A}
  1129.     bind $ew <Escape><KeyPress-6> {be:argkey %W %A}
  1130.     bind $ew <Escape><KeyPress-7> {be:argkey %W %A}
  1131.     bind $ew <Escape><KeyPress-8> {be:argkey %W %A}
  1132.     bind $ew <Escape><KeyPress-9> {be:argkey %W %A}
  1133.     bind $ew <Escape><KeyPress-minus> {be:argkey %W %A}
  1134.  
  1135.     bind $ew <Control-a> {be:begin-line %W}
  1136.     bind $ew <Control-e> {be:end-line %W}
  1137.     bind $ew <Control-b> {be:move-char %W -1}
  1138.     bind $ew <Control-f> {be:move-char %W 1}
  1139.     bind $ew <Escape><b> {be:move-word %W -1}
  1140.     bind $ew <Escape><f> {be:move-word %W 1}
  1141.  
  1142.     bind $ew <Control-l> {
  1143.     tk_entrySeeCaret %W
  1144.     }
  1145.  
  1146.     bind $ew <Control-d> {be:delete-back-char-or-sel %W 0}
  1147.     bind $ew <Escape><KeyPress-d> {be:delete-word %W 1}
  1148.     bind $ew <Control-k> {be:delete-line %W}
  1149.     bind $ew <Control-w> {be:delete-region-or-sel %W}
  1150.     bind $ew <Escape><KeyPress-w> {be:copy-region-or-sel %W}
  1151.     bind $ew <Control-y> {be:yank %W}
  1152.     bind $ew <Escape><KeyPress-y> {be:yank-pop %W}
  1153.     bind $ew <Control-space> {be:set-mark %W}
  1154.  
  1155.     bind $ew <Control-h> {be:delete-back-char-or-sel %W 1}
  1156.  
  1157.     # make C-x key a state
  1158.     bind $ew <Control-x> { }
  1159.     bind $ew <Control-x><Any-KeyPress> {
  1160.         global btp
  1161.     if {"%A" != ""} {eval $btp(beep) }
  1162.     }
  1163.     bind $ew <Control-x><Control-x> {be:exchange-point-and-mark %W}
  1164.  
  1165.     # Make Meta key like and Escape prefix
  1166.     if {$btp(use-meta)} {
  1167.     bind $ew <Meta-KeyPress> {
  1168.         global btp
  1169.         if {"%A" != ""} {eval $btp(beep) }
  1170.     }
  1171.     bind $ew <Control-Meta-KeyPress> {
  1172.         global btp
  1173.         if {"%A" != ""} {eval $btp(beep) }
  1174.     }
  1175.         bind $ew <Meta-b> {be:move-word %W -1}
  1176.         bind $ew <Meta-f> {be:move-word %W 1}
  1177.         bind $ew <Meta-d> {be:delete-word %W 1}
  1178.     bind $ew <Meta-w> {be:copy-region-or-sel %W}
  1179.     bind $ew <Meta-y> {be:yank-pop %W}
  1180.  
  1181.     bind $ew <Meta-0> {be:argkey %W %A}
  1182.     bind $ew <Meta-1> {be:argkey %W %A}
  1183.     bind $ew <Meta-2> {be:argkey %W %A}
  1184.     bind $ew <Meta-3> {be:argkey %W %A}
  1185.     bind $ew <Meta-4> {be:argkey %W %A}
  1186.     bind $ew <Meta-5> {be:argkey %W %A}
  1187.     bind $ew <Meta-6> {be:argkey %W %A}
  1188.     bind $ew <Meta-7> {be:argkey %W %A}
  1189.     bind $ew <Meta-8> {be:argkey %W %A}
  1190.     bind $ew <Meta-9> {be:argkey %W %A}
  1191.     bind $ew <Meta-minus> {be:argkey %W %A}
  1192.     }
  1193. }
  1194.  
  1195.